package httpproxymiddleware

import (
	"errors"
	"fmt"
	"go-gateway-learn/dao"
	"go-gateway-learn/middleware"
	"go-gateway-learn/public"

	"github.com/gin-gonic/gin"
)

func HTTPFlowLimitMiddleware() gin.HandlerFunc{
	return func (c *gin.Context)  {
		serverInterface, ok := c.Get("service")
		if !ok{
			middleware.ResponseError(c, 2001, errors.New("service not found"))
			c.Abort()
			return
		}
		serviceDetail := serverInterface.(*dao.ServiceDetail)
		serviceFlowLimit := serviceDetail.AccessControl.ServiceFlowLimit
		if serviceFlowLimit !=0{
			serviceLimiter, err := public.FlowLimiterHandler.GetLimiter(
				public.FlowServicePrefix+serviceDetail.Info.ServiceName,
				float64(serviceFlowLimit))
			if err != nil {
				middleware.ResponseError(c, 5001, err)
				c.Abort()
				return
			}
			if !serviceLimiter.Allow() {
				middleware.ResponseError(c, 5002, fmt.Errorf("service flow limit %v", serviceDetail.AccessControl.ServiceFlowLimit), )
				c.Abort()
				return
			}
		}
		clientFlowLimit := serviceDetail.AccessControl.ClientIPFlowLimit
		if clientFlowLimit !=0{
			clientLimiter, err := public.FlowLimiterHandler.GetLimiter(
				public.FlowServicePrefix+serviceDetail.Info.ServiceName+"_"+c.ClientIP(),
				float64(clientFlowLimit))
			if err != nil {
				middleware.ResponseError(c, 5003, err)
				c.Abort()
				return
			}
			if !clientLimiter.Allow() {
				middleware.ResponseError(c, 5002, fmt.Errorf("%v flow limit %v", c.ClientIP(), serviceDetail.AccessControl.ClientIPFlowLimit), )
				c.Abort()
				return
			}
		}
		c.Next()
	}
}